<?php

declare(strict_types=1);

namespace app\index\logic\order;

use app\index\logic\BaseLogic;
use app\common\model\order\ShipOrder as ShipOrderModel;
use app\common\model\order\Order as OrderModel;
use think\facade\Db;
use think\facade\Log;
use app\common\model\order\ShipOrderTakeChildren;
use app\common\ConstVar;
use app\common\service\third_party_api\ShipApiService;

/**
 * 船票订单逻辑层
 * 处理船票订单相关的业务逻辑
 */
class ShipOrderLogic extends BaseLogic
{
    /**
     * 船票订单模型实例
     * @var ShipOrderModel
     */
    protected $shipOrderModel;

    public function __construct()
    {
        $this->shipOrderModel = new ShipOrderModel();
    }

    /**
     * 获取订单中还未退款的游客列表
     * @param int $orderId 订单ID
     * @param int $userId 用户ID（可选，用于验证权限）
     * @return array 未退款的游客列表
     */
    public function getUnrefundContactList(int $orderId, int $userId = 0): array
    {
        // 如果提供了用户ID，验证订单归属
        if ($userId > 0) {
            $order = $this->shipOrderModel->where('id', $orderId)->where('user_id', $userId)->find();
            if (!$order) {
                return [];
            }
        } else {
            // 如果没有提供用户ID，直接获取订单信息
            $order = $this->shipOrderModel->where('id', $orderId)->find();
            if (!$order) {
                return [];
            }
        }

        // 获取订单的所有游客列表
        $contactList = json_decode($order['contact_list'], true);
        if (!is_array($contactList)) {
            $contactList = [];
        }

        // 获取该订单已退款的游客列表
        $refundedList = [];
        $partialRefunds = Db::name('ship_order_partial_refund')
            ->where('ship_order_id', $orderId)
            ->select();

        if ($partialRefunds) {
            foreach ($partialRefunds as $refund) {
                $refundedContact = json_decode($refund['refund_list'], true);
                if (is_array($refundedContact)) {
                    $refundedList = array_merge($refundedList, $refundedContact);
                }
            }
        }

        // 过滤出未退款的游客列表
        $unrefundContactList = array_filter($contactList, function ($contact) use ($refundedList) {
            // 检查当前游客是否在已退款列表中
            foreach ($refundedList as $refunded) {
                // 假设id_num和CardId是对应关系
                if (isset($contact['id_num'], $refunded['CardId']) && $contact['id_num'] === $refunded['CardId']) {
                    return false;
                }
            }
            return true;
        });

        // 重置数组索引
        return array_values($unrefundContactList);
    }

    /**
     * 获取用户船票订单列表
     * @param int $userId 用户ID
     * @param int $page 页码
     * @param int $limit 每页数量
     * @param string $status 订单状态
     * @return array
     */
    public function getUserShipOrders(int $userId, int $page = 1, int $limit = 10, string $status = ''): array
    {
        $query = $this->shipOrderModel->where('user_id', $userId);

        if (!empty($status)) {
            $query->where('status', $status);
        }

        return $query->order('create_time', 'desc')
            ->page($page, $limit)
            ->select()
            ->toArray();
    }

    /**
     * 检查船票订单是否可退款
     * @param int $orderId 订单ID
     * @param int $userId 用户ID
     * @return array
     */
    public function canRefundShipOrder(int $orderId, int $userId): array
    {
        $order = $this->shipOrderModel->where('id', $orderId)->where('user_id', $userId)->find();

        if (empty($order)) {
            return ['can_refund' => false, 'message' => '订单不存在'];
        }

        // 检查订单状态
        if ($order['status'] !== $this->shipOrderModel->STATUS_PAID) {
            return ['can_refund' => false, 'message' => '只有已支付订单才能退款'];
        }

        // 检查是否超过退款期限（24小时内可退）
        if (time() - $order['pay_time'] > 24 * 3600) {
            return ['can_refund' => false, 'message' => '已超过退款期限（24小时）'];
        }

        return ['can_refund' => true, 'message' => '可以退款'];
    }

    /**
     * 申请退款
     * @param int $orderId 订单ID
     * @param int $userId 用户ID
     * @param string $reason 退款原因
     * @param array $refundList 需要退款的游客列表，为空表示全部退款
     * @return array
     */
    public function applyRefundShipOrder(int $orderId, int $userId, string $reason = '', array $refundList = []): array
    {
        $canRefund = $this->canRefundShipOrder($orderId, $userId);

        if (!$canRefund['can_refund']) {
            return ['success' => false, 'message' => $canRefund['message']];
        }

        try {
            Db::startTrans();

            // 判断是部分退款还是全部退款
            $isFullRefund = empty($refundList);
            $status = $isFullRefund ? $this->shipOrderModel->STATUS_FULL_REFUND : $this->shipOrderModel->STATUS_PARTIAL_REFUND;

            // 更新订单状态
            $updateResult = $this->shipOrderModel->where('id', $orderId)->update([
                'status' => $status,
                'refund_reason' => $reason,
                'refund_apply_time' => time(),
                'update_time' => time()
            ]);

            if (!$updateResult) {
                Db::rollback();
                return ['success' => false, 'message' => '退款申请失败'];
            }

            // 如果是部分退款，记录部分退款信息
            if (!$isFullRefund && !empty($refundList)) {
                Db::name('ship_order_partial_refund')->insert([
                    'ship_order_id' => $orderId,
                    'refund_list' => json_encode($refundList),
                    'create_time' => time(),
                    'update_time' => time()
                ]);
            } else {
                // 记录退款日志
                Db::name('ship_order_refund')->insert([
                    'order_id' => $orderId,
                    'user_id' => $userId,
                    'reason' => $reason,
                    'create_time' => time()
                ]);
            }

            Db::commit();
            return ['success' => true, 'message' => $isFullRefund ? '全部退款申请已提交' : '部分退款申请已提交'];
        } catch (\Exception $e) {
            Db::rollback();
            Log::error('申请退款异常: ' . $e->getMessage() . ' - 订单ID: ' . $orderId);
            return ['success' => false, 'message' => '系统繁忙，请稍后重试'];
        }
    }

    /**
     * 计算订单总价
     * @param array $orderData 订单数据
     * @return float
     */
    public function calculateTotalPrice(array $orderData): float
    {
        $basePrice = floatval($orderData['price'] ?? 0);
        $quantity = intval($orderData['quantity'] ?? 1);
        $insurance = floatval($orderData['insurance'] ?? 0);
        $serviceFee = floatval($orderData['service_fee'] ?? 0);

        return $basePrice * $quantity + $insurance + $serviceFee;
    }

    /**
     * 获取订单详情
     * @param int $id 订单ID
     * @return array 订单详情
     */
    public function getOrderDetail(int $id): array
    {
        $order = $this->shipOrderModel->where('id', $id)->find();

        if (!$order) {
            return ['order' => []];
        }

        $order = $order->toArray();

        // 处理changeVoyage关联
        $changeVoyage = Db::name('change_voyage')
            ->where('ship_order_id', '=', $id)
            ->where('code', '=', '10001')
            ->find();
        $order['change_voyage'] = $changeVoyage ? (array)$changeVoyage : null;

        $orderMoney = 0;
        $now = time();

        // 格式化数据
        $from = mb_substr($order['choose_flight']['FromPortName'], 0, 2);
        $to = mb_substr($order['choose_flight']['ToPortName'], 0, 2);
        $order['title'] = $order['choose_flight']['ShipCode'] . $from . '-' . $to . ' ' . $order['choose_flight']['ShipName'] . ' ' . $order['choose_seat']['SeatName'];
        $order['timer'] = intval($order['create_time']) + ShipOrderModel::DELAY_TIME - $now;
        $order['create_time'] = date('Y-m-d H:i:s', $order['create_time']);
        $order['departure_time'] = date('Y-m-d H:i:s', $order['departure_time']);
        $order['status_text'] = $this->getShipOrderStatusLabel($order['status']) ?? '';
        $order['tourist_num'] = count($order['contact_list']);
        $order['show_pay'] = 0;
        if (intval($order['status']) === $this->shipOrderModel->STATUS_UNPAID && $order['timer'] > 0) {
            $order['show_pay'] = 1;
        }
        if ($order['shipline']) {
            $order['line_text'] = $order['shipline']['FromCityName'] . '-' . $order['shipline']['ToCityName'];
        } else {
            $order['line_text'] = '';
        }

        //获取小童信息计算手续费
        $take_children = Db::name('ship_order_take_children')->where(['ship_order_id' => $id])->select();
        // 查找系统配置表中的手续费设置（假设使用app_config表替代不存在的system表）
        $ship_charges = Db::name('app_config')->where('name', 'ship_charges')->find();
        $order['total'] += floatval(count($take_children) * $ship_charges['value']);

        //获取本单剩余可部分退款的名单信息
        $refund_list = Db::name('ship_order_partial_refund')->where(['ship_order_id' => $id])->select();
        $order['refunded_list'] = [];
        if ($refund_list) {
            foreach ($refund_list as $item) {
                $order['refunded_list'] = array_merge($order['refunded_list'], json_decode($item['refund_list'], true));
            }
        }
        //比较获取contact_list和refunded_list二维数组中username不同的部分
        $order['refund_list'] = array_values(array_filter($order['contact_list'], function ($contact) use ($order) {
            foreach ($order['refunded_list'] as $refunded) {
                if ($contact['id_num'] === $refunded['CardId']) {
                    return false;
                }
            }
            return true;
        }));

        //判断是否还有可部分退款的用户
        $order['show_partial_refund'] = 0;
        if (count($order['refund_list']) && $order['status'] == $this->shipOrderModel->STATUS_PARTIAL_REFUND) {
            $order['show_partial_refund'] = 1;
        }

        //开船时间
        if ($order['choose_flight']) {
            $order['go_time'] = $order['choose_flight']['DepartureDate'];
        }

        //申请改签
        $order['show_change'] = 0;
        if (isset($order['choose_flight']['DepartureDate']) && strtotime($order['choose_flight']['DepartureDate']) > $now && $order['GetTicketNOResult'] == 1 && $order['status'] == OrderModel::UN_PAID) {
            $order['show_change'] = 1;
        }
        $order['show_refund'] = 1;
        if (!in_array($order['status'], [$this->shipOrderModel->STATUS_PAID, $this->shipOrderModel->STATUS_REFUNDING])) {
            $order['show_refund'] = 0;
        }
        if ($order['GetTicketNOResult'] != 1) {
            $order['show_refund'] = 0;
        }
        //判断距离开船时间2小时内不给退票
        if (strtotime($order['go_time']) - $now <= 2 * 60 * 60) {
            $order['show_refund'] = 0;
        }
        if ($order['change_voyage']) {
            $order['change_voyage']['body'] = json_decode($order['change_voyage']['body_arr'], true);
            if (strtotime($order['change_voyage']['body']['date']) < $now) {
                $order['show_refund'] = 0;
            }
        } else {
            if (!isset($order['choose_flight']['DepartureDate']) || strtotime($order['choose_flight']['DepartureDate']) < $now) {
                $order['show_refund'] = 0;
            }
        }

        // 处理商品订单
        $orderMoney = floatval($order['total_price']) + floatval($order['charge']);
        if (isset($order['goods_order']) && $order['goods_order']) {
            foreach ($order['goods_order'] as &$item) {
                $item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
                if ($item['is_del'] === 1) {
                    $item['status_text'] = '已取消';
                } else {
                    $item['status_text'] = (null !== $this->getShipOrderStatusLabel($item['status'])) ? $this->getShipOrderStatusLabel($item['status']) : '';
                }
                $orderMoney = $orderMoney + floatval($item['order_money']);
            }
        }
        $order['order_money'] = $orderMoney;

        return ['order' => $order];
    }

    /**
     * 记录用户无座位协童登记数据
     * @param int $ship_order_id 船票订单ID
     * @param array $take_children 儿童信息数组
     * @param int $user_id 用户ID
     * @return bool
     */
    public function recordChildrenData(int $ship_order_id, array $take_children, int $user_id): bool
    {
        if (empty($take_children)) {
            return true;
        }

        $data = [];
        foreach ($take_children as $item) {
            if (!empty($item['child_name']) && !empty($item['id_num'])) {
                $data[] = [
                    'user_id' => $user_id,
                    'ship_order_id' => $ship_order_id,
                    'child_name' => $item['child_name'],
                    'id_num' => $item['id_num'],
                    'create_time' => time(),
                    'update_time' => time(),
                ];
            }
        }

        if (empty($data)) {
            return false;
        }

        try {
            return (new ShipOrderTakeChildren())->insertAll($data) > 0;
        } catch (\Exception $e) {
            Log::error('记录儿童登记数据异常: ' . $e->getMessage() . ' - 订单ID: ' . $ship_order_id);
            return false;
        }
    }

    /**
     * 获取订单状态文本
     * @param int $status 状态码
     * @return string
     */
    private function getShipOrderStatusLabel(int $status): string
    {
        $labels = [
            $this->shipOrderModel->STATUS_NORMAL => '正常',
            $this->shipOrderModel->STATUS_CHANGED => '已改签',
            $this->shipOrderModel->STATUS_PARTIAL_REFUND => '已部分退款',
            $this->shipOrderModel->STATUS_FULL_REFUND => '已全部退款',
            $this->shipOrderModel->STATUS_COMPLETED => '已完成',
        ];
        return $labels[$status] ?? '';
    }

    /**
     * 船票订单改签
     * @param int $id 订单ID
     * @param int $userId 用户ID
     * @param array $param 改签参数
     * @return array 改签结果
     */
    public function changeShipOrder(int $id, int $userId, array $param): array
    {
        try {
            // 获取订单信息
            $orderInfo = $this->shipOrderModel->where('id', $id)->where('user_id', $userId)->find();

            if (!$orderInfo) {
                Log::error('订单不存在或无权限操作，订单ID: ' . $id . ', 用户ID: ' . $userId);
                return ['success' => false, 'message' => '订单不存在或无权限操作'];
            }

            // 检查订单状态是否可改签
            if ($orderInfo['status'] != $this->shipOrderModel::STATUS_NORMAL || $orderInfo['GetTicketNOResult'] != 1) {
                Log::error('订单状态不允许改签，订单ID: ' . $id);
                return ['success' => false, 'message' => '订单状态不允许改签'];
            }

            // 构建改签请求参数
            $body_arr = [
                'orderSerialId' => $orderInfo['tc_order_no'], // 同程订单流水号
                'tickets' => $param['newVoyageId'] ?? '', // 票code（多个票code用逗号隔开）
                'date' => $param['date'] ?? '', // 改签后发船日期
                'shipName' => $param['shipName'] ?? '', // 改签船名
                'cabinId' => $param['cabinId'] ?? '', // 改签舱位id
                'cabinName' => $param['cabinName'] ?? '', // 改签舱位名称
                'cardNos' => $param['cardNos'] ?? '', // 改签客人证件号（多个证件号用逗号隔开）
            ];

            // 调用船票改签接口进行改签
            $shipApiService = new ShipApiService();
            $result = $shipApiService->changeOrder($body_arr);

            // 记录改签请求日志
            Log::error('船票改签请求，订单ID: ' . $id . '，请求参数: ' . json_encode($body_arr) . '，响应结果: ' . json_encode($result));

            // 处理改签结果
            if ($result['code'] == 10001) {
                // 改签成功，更新本地订单状态
                $updateData = [
                    'status' => $this->shipOrderModel::STATUS_CHANGED,
                    'update_time' => time(),
                    'tc_notify' => json_encode($result),
                ];

                // 如果有新的航班信息，更新订单中的航班信息
                if (!empty($param['newFlightInfo'])) {
                    $updateData['choose_flight'] = json_encode($param['newFlightInfo']);
                }

                Db::startTrans();

                // 记录改签信息到change_voyage表
                Db::name('change_voyage')->insert([
                    'ship_order_id' => $id,
                    'body_arr' => json_encode($body_arr),
                    'response' => json_encode($result),
                    'code' => $result['code'],
                    'message' => $result['message'] ?? '',
                    'create_time' => time(),
                    'update_time' => time(),
                ]);

                // 更新订单状态
                $this->shipOrderModel->where('id', $id)->update($updateData);

                Db::commit();
                return ['success' => true, 'message' => '改签成功'];
            } else {
                // 改签失败
                Log::error('船票改签失败，订单ID: ' . $id . '，错误信息: ' . ($result['message'] ?? '未知错误'));
                return ['success' => false, 'message' => $result['message'] ?? '改签失败，请稍后重试'];
            }
        } catch (\Exception $e) {
            Db::rollback();
            Log::error('船票改签异常，订单ID: ' . $id . '，异常信息: ' . $e->getMessage());
            return ['success' => false, 'message' => '系统繁忙，请稍后重试'];
        }
    }

    /**
     * 同程出票
     * @param array $shipOrder 船票订单数据
     * @param bool $lockFirst 是否先锁票
     * @return array 出票结果
     */
    public function tcShipTicket(array $shipOrder, bool $lockFirst = false): array
    {
        Log::error('同程出票请求,订单Id:' . $shipOrder['ship_order_id']);
        $bool = true;
        $total = bcsub($shipOrder['total_amount'], $shipOrder['bao_fee'], 2);

        $order_id = uniqid();
        $TakeOffDateTime = '';
        $shipOrderId = $shipOrder['ship_order_id'];
        $ContactName = $shipOrder['contact_list'][0]['username'];
        $ContactIdType = array_search($shipOrder['contact_list'][0]['id_type'], ConstVar::$ContactIdType);
        $ContactIdCard = $shipOrder['contact_list'][0]['id_num'];
        $ContactNo = $shipOrder['booking_tel'];
        Log::error('同程出票请求,订单Id:' . $shipOrder['ship_order_id'] . '，签名');

        $body_arr = [
            'ShipLineId' => $shipOrder['chooseFlight']['LineId'],
            'userid' => env('tc_user_id'),
            'OrderID' => $order_id,
            'VoyageId' => $shipOrder['chooseFlight']['VoyageId'],
            'SeatId' => $shipOrder['chooseSeat']['SeatId'],
            'SeatName' => $shipOrder['chooseSeat']['SeatName'],
            'ShipSeatType' => $shipOrder['chooseSeat']['ShipSeatType'],
            'Departure' => $shipOrder['shipline']['FromCityName'],
            'DeparturePort' => $shipOrder['chooseFlight']['FromPortName'],
            'Destination' => $shipOrder['shipline']['ToCityName'],
            'ArrivePort' => $shipOrder['chooseFlight']['ToPortName'],
            'DepartureTime' => $shipOrder['chooseFlight']['DepartureDate'],
            'ShipRunMinutes' => $shipOrder['chooseFlight']['ShipRunMinutes'],
            'ContactName' => $ContactName,
            'ContactNo' => $ContactNo,
            'ContactIdType' => $ContactIdType,
            'ContactIdCard' => $ContactIdCard,
            'TicketAmount' => $total,
            'TicketCount' => count(json_decode($shipOrder['PassengersInfo'], true)),
            'PassengersInfo' => json_decode($shipOrder['PassengersInfo'], true),
            'TakeOffDateTime' => $TakeOffDateTime,
            'LockFirst' => $lockFirst,
        ];
        Log::error('同程出票请求,订单Id:' . $shipOrder['ship_order_id'] . '，请求结果');
        try {
            $shipapi = new ShipApiService();
            $body = $shipapi->createOrder($body_arr);
            $bodyJson = json_encode($body);
            Log::error('请求结果:' . $bodyJson);
        } catch (\Exception $e) {
            $body = [
                'code' => -1,
                'message' => $e->getMessage()
            ];
        }

        $updateData = [
            'self_order_no' => $order_id,
            'body_arr' => json_encode($body_arr),
            'response' => json_encode($body),
        ];

        //先锁票
        if ($lockFirst) {
            if ($body['code'] != 100047) {
                return ['bool' => false, $body['data']];
            } else {
                $updateData = array_merge($updateData, [
                    'tc_order_no' => $body['data'] ? $body['data'] : '',
                    'status' => 1,         //待支付
                    'GetTicketNOResult' => 1
                ]);

                $this->shipOrderModel->where('ship_order_id', $shipOrderId)->update($updateData);

                return ['bool' => true, $body['message']];
            }
        } else { //正常出票
            //出票成功
            if ($body['code'] == 20031) {
                $updateData = array_merge($updateData, [
                    'tc_order_no' => $body['data'] ? $body['data'] : '',
                    'status' => 2,         //待出票
                    'GetTicketNOResult' => 1
                ]);
            } else {
                $updateData = array_merge($updateData, [
                    'status' => 10,         //出票失败
                ]);
                $bool = false;
            }
            $this->shipOrderModel->where('ship_order_id', $shipOrderId)->update($updateData);
            return ['bool' => $bool, $body['message']];
        }
    }
}
